package com.core.pf;

import java.util.List;
import java.util.Iterator;

import org.hibernate.Session;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.criterion.SimpleExpression;
import com.core.locator.ServiceLocator;
import com.core.pf.RetrieveCriteria.Order;

/**
 * 
 * @author jorge
 *
 */
public class PersistentBroker {

  // Atomicos
  private Session session;
    
   /**
    * Constructor
    */
    public PersistentBroker() {}
    
    /**
     * Salva o actualiza un objeto
     * @param persistenObject
     */
    public void saveObject(Object perObject) {
        
        try {
            session = ServiceLocator.getInstanceSessionFactory().openSession();
           	session.saveOrUpdate(perObject);
           	session.flush();
        }
        catch(HibernateException hex) {
            throw new PersistentException("Error al salvar el objeto " + perObject.getClass().getName(),
                    this.getClass(), hex);
        }
        finally {
            try {
                if(session != null) {
                    session.close();
                }
            }
            catch(Exception ex){}
        }
    }
    
    /**
     * Elimina un objeto
     * @param criteria
     */
    public void deleteObject(RetrieveCriteria criteria) {
        
        try {
            session = ServiceLocator.getInstanceSessionFactory().openSession();
            Object delObj = retrieveObject(criteria);
            session.delete(delObj);
            session.reconnect();
            session.flush();
        }
        catch(HibernateException hex) {
            throw new PersistentException("Error al eliminar el objeto " + criteria.getClase().getName(),
                    this.getClass(), hex);
        }
        finally {
            try {
                if(session != null) {
                    session.close();
                }
            }
            catch(Exception ex) {}
        }
    }
    
    /**
     * Obtener los objetos de la clase segun el criterio especificado
     * @param criteria, asProxy
     * @return
     */
    @SuppressWarnings("unchecked")
	public List processCriteria(RetrieveCriteria criteria) {
		
        try {
            session = ServiceLocator.getInstanceSessionFactory().openSession();
            Criteria hbCriteria = session.createCriteria(criteria.getClase());
            
            if(criteria.getConditions().size() > 0) {
                Iterator itCondition = criteria.getConditions().iterator();
                
                while(itCondition.hasNext()) {
                    SimpleExpression exp = (SimpleExpression) itCondition.next();
                    hbCriteria.add(exp);
                }                
            }
            
            if(criteria.getOrders().size() > 0) {
            	Iterator itOrder = criteria.getOrders().iterator();
            	
            	while(itOrder.hasNext()) {
            		Order order = (Order) itOrder.next();
            		
            		hbCriteria.addOrder((order.getTypeOrder() == RetrieveCriteria.ASCENDING ? 
            				org.hibernate.criterion.Order.asc(order.getField()) :
            					org.hibernate.criterion.Order.desc(order.getField())));
            	}
            }
            
            List results = hbCriteria.list();
		
            return results;
        }
        catch(HibernateException hex) {
            throw new PersistentException("Error al obtener las " + criteria.getClase().getName(),
                    this.getClass(), hex);
        }
        finally {
            try {
                if(session != null) {
                    session.close();
                }
            }
            catch(Exception ex) {}
        }
    }
    
    /**
     * Obtiene un objeto por pk
     * @param criteria
     * @return
     */
    public Object retrieveObject(RetrieveCriteria criteria) {
        
        Object result = null;
        try {
            if(criteria.getPkObj() != null) {
                session = ServiceLocator.getInstanceSessionFactory().openSession();
                Long obj = (Long) criteria.getPkObj();
                result = session.get(criteria.getClase(), obj);
            }
            
           return result;
        }
        catch(HibernateException hex) {
            throw new PersistentException("Error al obtener el objeto " + criteria.getClase().getName(),
                    this.getClass(), hex);
        }
        finally {
            try {
                if(session != null) {
                    session.close();
                }
            }
            catch(Exception ex) {}
       }
    }

    /**
     * Obtiene un objeto por pk
     * @param criteria
     * @return
     */
    public Object retrieveObjectString(RetrieveCriteria criteria) {
        
        Object result = null;
        try {
            if(criteria.getPkObj() != null) {
                session = ServiceLocator.getInstanceSessionFactory().openSession();
                String obj = (String) criteria.getPkObj();
                result = session.get(criteria.getClase(), obj);
            }
            
           return result;
        }
        catch(HibernateException hex) {
            throw new PersistentException("Error al obtener el objeto " + criteria.getClase().getName(),
                    this.getClass(), hex);
        }
        finally {
            try {
                if(session != null) {
                    session.close();
                }
            }
            catch(Exception ex) {}
       }
    }
    
}
